home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smtp / smtpd.4.2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  5.1 KB  |  237 lines

  1. /*
  2.  *            S M T P D . C
  3.  *
  4.  * Server SMTP daemon, for 4.1a/4.2 BSD by DPK at BRL, 1 Jan 82 (Sigh...)
  5.  *
  6.  *        R E V I S I O N   H I S T O R Y
  7.  *
  8.  *    02/02/83  MJM   Modified to be more robust.
  9.  *
  10.  *    03/18/83  DPK   Modified for 4.1c.
  11.  *
  12.  *    ??        Modified for 4.2
  13.  */
  14.  
  15. #include "util.h"
  16. #include <signal.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netdb.h>
  20. #include <sys/wait.h>
  21. #include <sys/ioctl.h>
  22.  
  23. #include "ns.h"
  24.  
  25. extern    int    errno;
  26.  
  27. struct    sockaddr_in    addr;
  28.  
  29. char    *Smtpserver = 0;    /* Actual smtp server process, full path */
  30. char    *Channel = 0;        /* Logical channel mail will arrive on */
  31. int    Maxconnections = 4;    /* Maximum simultaneous connections */
  32. int    numconnections = 0;    /* Number of currently active connections */
  33. int    debug = 0;        /* If nonzero, give verbose output on stderr */
  34. #define    logx    if (debug) log
  35. char    errbuf[BUFSIZ];        /* Logging will be line buffered */
  36. char    programid[40];        /* identification string for log entries */
  37. int    stricked;        /* force full validity of source address */
  38.  
  39. main (argc, argv)
  40. int argc;
  41. char **argv;
  42. {
  43.     register    int        skt;
  44.             struct    servent    *sp;
  45.             struct    hostent    *hp;
  46.             char        thishost[64];
  47.             char        workarea[32];
  48.             int        i, pid;
  49.  
  50.     setbuf(stderr, errbuf);
  51.     sprintf(programid, "smtpd(%5.5d): ", getpid());
  52.     gethostname(thishost, sizeof(thishost));    /* current hostname */
  53.     if ((sp = getservbyname("smtp", "tcp")) == NULL) {
  54.         fprintf(stderr, "Cannot find service smtp/tcp\n");
  55.         exit(-1);
  56.     }
  57. #ifdef NAMESERVER
  58.     /* don't wait forever! */
  59.     ns_settimeo(NS_NETTIME);
  60. #endif /* NAMESERVER */
  61.  
  62.     /*
  63.      * try to get full name for thishost
  64.      */
  65.     if ((hp = gethostbyname(thishost)) != NULL)
  66.         strcpy(thishost, hp->h_name);
  67.  
  68.     /* Parse args; args will override configuration file... */
  69.     arginit(argc, argv);
  70.  
  71.     addr.sin_addr.s_addr = AF_INET;
  72.     addr.sin_addr.s_addr = INADDR_ANY;
  73.     addr.sin_port = (short)sp->s_port;
  74.  
  75.     if ((i = open("/dev/tty", 2)) >= 0) {
  76.         (void) ioctl(i, TIOCNOTTY, (char *)0);
  77.         (void) close(i);
  78.     }
  79.  
  80.     /*
  81.      * Create a socket to accept a SMTP connection on.
  82.      * The doloop is due to some sort of IPC bug in 4.1a.
  83.      */
  84.     logx("opening socket...");
  85.     i = 60;
  86.     do {
  87.         skt = socket(AF_INET, SOCK_STREAM, 0, 0);
  88.         logx("socket returned %d", skt);
  89.         if (skt < 0)
  90.             sleep(5);
  91.     } while (skt < 0 && i-- > 0);
  92.     if (skt < 0) {
  93.         logx("can't open socket (errno %d)", errno);
  94.         exit(99);
  95.     }
  96.     logx("socket open on %d", skt);
  97.  
  98.     if (bind (skt, (char *)&addr, sizeof addr, 0) < 0) {
  99.         logx("can't bind socket (errno %d)", errno);
  100.         exit(98);
  101.     }
  102.     listen (skt, Maxconnections+1);
  103.  
  104.     while (1) {
  105.         extern    char            *inet_ntoa();
  106.             struct    sockaddr_in    rmtaddr;
  107.             int            len_rmtaddr = sizeof rmtaddr;
  108.             int            tmpskt;
  109.             int            status;
  110.  
  111.         /*
  112.          * Accept a connection.
  113.          */
  114.         if ((tmpskt = accept(skt, &rmtaddr, &len_rmtaddr, 0)) < 0) {
  115.             logx("accept error (%d)", errno);
  116.             sleep(1);
  117.             continue;
  118.         }
  119.  
  120.         /* We have a valid open connection, start a server... */
  121.         if ((pid = fork()) < 0) {
  122.             logx("could not fork (%d)", errno);
  123.             close(tmpskt);
  124.         } else if (pid == 0) {
  125.             /*
  126.              * Child
  127.              */
  128.             char    *rmt;
  129.  
  130.             hp = gethostbyaddr(&rmtaddr.sin_addr,
  131.                     sizeof(rmtaddr.sin_addr), AF_INET);
  132.             if ((hp == NULL) || !isstr(hp->h_name)) {
  133.                 strcpy(workarea, inet_ntoa(rmtaddr.sin_addr));
  134.                 rmt = workarea;
  135.             }
  136.             else
  137.                 rmt = hp->h_name;
  138.  
  139.             logx("%s started", rmt);
  140.             dup2(tmpskt, 0);
  141.             dup2(tmpskt, 1);
  142.             if (tmpskt > 1)
  143.                 close(tmpskt);
  144.             execl(Smtpserver, stricked? "rsmtpsrvr" : "smtpsrvr",
  145.                     rmt, thishost, Channel, (char *)0);
  146.             logx("server exec error (%d)", errno);
  147.             exit(99);
  148.         }
  149.  
  150.         /*
  151.          * Parent
  152.          */
  153.         close(tmpskt);
  154.         numconnections++;
  155.  
  156.         /*
  157.          * This code collects ZOMBIES and implements load
  158.          * limiting by staying in the do loop while the
  159.          * Maxconnections active.
  160.          */
  161.         while (wait3 (&status, numconnections < Maxconnections
  162.             ? WNOHANG : 0, 0) > 0)
  163.             numconnections--;
  164.     }
  165. }
  166.  
  167. arginit(argc, argv)
  168. int argc;
  169. char **argv;
  170. {
  171.     register    int    ch;
  172.     extern        char    *optarg;
  173.     extern        int    optind;
  174.  
  175.     while ((ch = getopt(argc, argv, "dfn:")) != EOF) {
  176.         switch (ch) {
  177.         case 'd':
  178.             debug++;
  179.             break;
  180.  
  181.         case 'f':    /* force correctness of addresses */
  182.             stricked++;
  183.             break;
  184.  
  185.         case 'n':
  186.             Maxconnections = atoi(optarg);
  187.             if (Maxconnections <= 0) {
  188.                 logx("Bad number of connections '%s'", optarg);
  189.                 exit(99);
  190.             }
  191.             logx("Maxconnection now %d", Maxconnections);
  192.             break;
  193.  
  194.         default:
  195.             log("Usage: %s [-df] [-n #connections] smtpserver channels", argv[0]);
  196.             exit(1);
  197.         }
  198.     }
  199.  
  200.     if (optind == argc) {
  201.         log("Usage: %s [-df] [-n #connections] smtpserver channels",
  202.             argv[0]);
  203.         exit(1);
  204.     }
  205.  
  206.     if (optind < argc) {
  207.         if (access(argv[optind], 01) < 0) {    /* execute privs? */
  208.             logx("Cannot access server program '%s'", argv[optind]);
  209.             exit(99);
  210.         }
  211.         Smtpserver = argv[optind];
  212.         logx("server is '%s'", Smtpserver);
  213.     } else {
  214.         logx("Smtpserver program not specified!");
  215.         exit(99);
  216.     }
  217.  
  218.     if (++optind < argc) {
  219.         Channel = argv[optind];
  220.         logx("channel is '%s'", Channel);
  221.     } else {
  222.         logx("Channel not specified!");
  223.         exit(99);
  224.     }
  225. }
  226.  
  227. /* VARARGS */
  228. log(fmt, a, b, c, d)
  229. char *fmt;
  230. int a, b, c, d;
  231. {
  232.     fputs(programid, stderr);
  233.     fprintf(stderr, fmt, a, b, c, d);
  234.     fputc('\n', stderr);
  235.     fflush(stderr);
  236. }
  237.